/*! \file scrollpanel.cpp	
	
	This contains the implementation of the ScrollPanel class
*/


#include "scrollpanel.h"

ScrollPanel::ScrollPanel( Component* parent ) :
	Container( parent ),
	vScrollBar( this, 3, 5, 4 )
{
}


void ScrollPanel::childChangedSize( Component* which ) {
	// Find the height of the child that changed size.
	int height = which->getHeight();
	
	// Find out the ScrollPanel's heightWithoutBorder
	int heightWithoutBorder = h - 2 * borderWidth;
	// The size of the slider should be the ratio of the height that the child can fit in to the height of
	// the child times the size of the track. I do the multiplication first because screw you.
	float sliderSize = heightWithoutBorder * vScrollBar.getTrackSize() / height;
	
	// The slider can't be smaller than a certain size.
	if ( sliderSize < 8 ) sliderSize = 8;
		
	// The furthest down you can scroll now is the difference in heights (in pixels) between the child and this.
	
	vScrollBar.setMaxPosition( height - heightWithoutBorder );
	
	// You can't have a slider bigger than the track!
	if ( sliderSize > vScrollBar.getTrackSize() ) {
		sliderSize = vScrollBar.getTrackSize();
	}
	
	// Finally, actually set the slider's height
	vScrollBar.getSlider()->setHeight( (int)sliderSize );
	
}

void ScrollPanel::update() {
	// Update all of its children
	list<Component*>::iterator i;
	for ( i = children.begin(); i != children.end(); ++i ) {
		(*i)->update();
	}
	
}
void ScrollPanel::setSize( int newW, int newH ) {
	// Update dimensions
	w = newW;
	h = newH;
	
	// Since the size of this changed, the scrollBar needs to be resized and repositioned
	vScrollBar.setHeight( newH );
	vScrollBar.setPosition( w - borderWidth - vScrollBar.getWidth(), 0 );
	
	// Set the width of all the children.
	list<Component*>::iterator i;
	for ( i = children.begin(); i != children.end(); ++i ) {
		if ( (*i) != &vScrollBar ) {
			(*i)->setWidth( w - borderWidth * 2 - vScrollBar.getWidth() );
		}
	}
	
	// You could be scrolled out-of-bounds now, so this function will make sure everything is in place.
	vScrollBar.updateScroll(); 
	vector<Listener*>::iterator j;
	for ( j = listeners.begin(); j != listeners.end(); ++j ) {
		(*j)->onSize( Event( this ) );
	}
	
}

void ScrollPanel::draw() {
	GUI::setClippingArea( getScreenX(), getScreenY(), w, h );
	
	if ( !visible ) {
		return;
	}
		
	//~ glPushMatrix();
	//~ glLoadIdentity();
	
	int screenX = getScreenX(), screenY = getScreenY();
	//~ glTranslatef( (float)screenX, (float)screenY, 0.0 );
	
	//~ GUI::getInstance()->drawRectangle( screenX, screenY, w, h, bgColorTop, bgColorBottom );
	GUI::getInstance()->drawRectangle( w, h, bgColorTop, bgColorBottom );
	// Iterate through its children and draw them. The parent positions
	// the start location of the child
	if ( !children.empty() ) {
		list<Component*>::iterator i;
		
		for ( i = children.begin(); i != children.end(); ++i ) {
			if ( (*i)->isVisible() ) {
				glPushMatrix();
				glTranslatef( (float)(*i)->getX(), (float)(*i)->getY() - vScrollBar.getSliderPosition(), 0.0f );
				(*i)->draw();
				glPopMatrix();
			}
		}
	}
	
	//~ glPopMatrix();
	
	
	if ( border != false ) {
		//~ ImageHandler::getInstance()->guiBorder( sideID1, cornerID1, screenX, screenY, w, h );
		ImageHandler::getInstance()->guiBorder( sideID1, cornerID1, w, h );
	}
	
	GUI::removeClippingArea();
}

bool ScrollPanel::handleMouseWheel( int pos ) {
	if ( !visible ) {
		return false;
	}
	
	vScrollBar.scrollByUnits( pos );
	
	vector<Listener*>::iterator j;
	for ( j = listeners.begin(); j != listeners.end(); ++j ) {
		(*j)->onScroll( Event( this, pos ) );
	}
	return true;
}

int ScrollPanel::getScrollPosition() {
	return vScrollBar.getSliderPosition();
}
void ScrollPanel::setWidth( int newW ) {
	setSize( newW, h );
}

void ScrollPanel::setHeight( int newH ) {
	setSize( w, newH );
}
int ScrollPanel::getScrollbarWidth() {
	return vScrollBar.getWidth();
}

void ScrollPanel::scrollToBottom() {
	vScrollBar.scrollToBottom();
}
